package ${groupId}.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import ${groupId}.pojo.MenuInfo;
import ${groupId}.pojo.RoleInfo;
import ${groupId}.pojo.UserInfo;
import ${groupId}.service.IndexService;
import ${groupId}.util.Result;
import ${groupId}.util.StringUtil;

@Controller
public class IndexController {
	
	@Autowired
	private IndexService indexService;
	
	@Value("${image_address}")
	private String image_address;
	
	/**
	 * 主页视图
	 * 判断用户是否登陆
	 * @param session 会话对象
	 * @return 如果已登陆，返回首页；否侧返回登录页。
	 */
	@RequestMapping(value = "/",method = {RequestMethod.POST, RequestMethod.GET})
	public String index(HttpSession session) {
		UserInfo userInfo = (UserInfo) session.getAttribute("USER_INFO");
		if (userInfo != null) {
			return "index";
		}
		return  "login";
	}
	
	/**
	 * 首页视图
	 * @return 首页
	 */
	@RequestMapping(value = "/console",method = {RequestMethod.POST, RequestMethod.GET})
	public String console() {
		return  "console";
	}
	
	/**
	 * 用户登陆视图
	 * @return 登陆页面
	 */
	@RequestMapping(value = "/toLogin",method = {RequestMethod.POST, RequestMethod.GET})
	public String toLogin() {
		return  "login";
	}
	
	/**
	 * 用户注册视图
	 * @return 注册页面
	 */
	@RequestMapping(value = "/toRegister",method = {RequestMethod.POST, RequestMethod.GET})
	public String toRegister() {
		return  "register";
	}
	
	/**
	 * 用户注销接口
	 * 清除会话
	 * 重定向访问根地址
	 */
	@RequestMapping(value = "/logout",method = {RequestMethod.POST, RequestMethod.GET})
	public String logout(HttpSession session){
		session.invalidate();
		return "redirect:/";
	}
	
	/**
	 * 用户列表视图
	 * @return 用户列表页面
	 */
	@RequestMapping(value = "/userInfoList",method = {RequestMethod.POST, RequestMethod.GET})
	public String userInfoList() {
		return  "userInfoList";
	}
	
	/**
	 * 获取当个用户表单视图的接口，根据会话对象获取当前登陆人信息，并调用服务层以主键查询单个用户信息的接口，查询出单个用户信息。
	 * 模型与视图对象封装此用户信息，并设置用户的表单视图。
	 * @param mav 模型与视图对象
	 * @param session 用户获取当前登陆人信息
	 * @return 返回模型与视图对象。
	 */
	@RequestMapping(value = "/selectUser",method = {RequestMethod.POST, RequestMethod.GET})
	public ModelAndView selectUser(ModelAndView mav,HttpSession session) {
		UserInfo userInfo = (UserInfo) session.getAttribute("USER_INFO");
		mav.addObject("anyOne",indexService.selectUser(userInfo));
		mav.setViewName("userInfoForm");
		return mav;
	}
	
	/**
	 * 用户登陆接口，调用服务层登陆接口，返回用户集合
	 * @param userInfo 携带用户名与密码的用户信息
	 * @param session 会话对象
	 * @return 如果集合长度为0，那么返回0；否则初始化用户会话，返回1
	 */
	@ResponseBody
	@RequestMapping(value = "/login",method = {RequestMethod.POST,RequestMethod.GET})
	public Result<String> login(UserInfo userInfo,HttpSession session) {
		userInfo = indexService.login(userInfo);
		if (StrUtil.isBlank(userInfo.getPrimaryKey())) {
			return new Result<String>(1,"登陆失败",0L,null);
		}
		session.setAttribute("USER_INFO", userInfo);
		return new Result<String>(0,"登陆成功",0L,null);
	}
	
	/**
	 * 注册用户接口
	 * 调用服务层注册用户的接口，判断是否已注册。
	 * @param userInfo 需要注册的用户信息
	 * @param session 用于设置用户信息
	 * @return 如果可以注册，那么查询出这个用户的所有信息，并设置在会话里，返回1；如果不可以注册，即返回0。
	 */
	@ResponseBody
	@RequestMapping(value = "/register",method = {RequestMethod.POST,RequestMethod.GET})
	public Result<String> register(UserInfo userInfo,HttpSession session) {
		if (indexService.register(userInfo) != 1) {
			return new Result<String>(1,"注册失败",0L,null);
		}
		userInfo = indexService.login(userInfo);
		session.setAttribute("USER_INFO", userInfo);
		return new Result<String>(0,"注册成功",0L,null);
	}
	
	/**
	 * 用户批量删除的接口，根据参数，调用服务层批量删除用户的接口。
	 * @param s 用户的主键列表，因为是js数组对象，所以需要用请求体接收。
	 * @return 返回受影响行数。
	 */
	@ResponseBody
	@RequestMapping(value = "/deleteUser",method = {RequestMethod.POST,RequestMethod.GET})
	public Result<String> deleteUser(UserInfo userInfo) {
		if ((indexService.deleteUser(userInfo)) != 1) {
			return new Result<String>(1,"删除失败",0L,null);
		}
		return new Result<String>(0,"删除成功",0L,null);
	}
	
	/**
	 * 分页查询用户的接口
	 * 首先，计算开始行与结束行；
	 * 其次，根据查询条件查询记录数；
	 * 最后，根据分页信息与查询条件，查询用户列表。
	 * @param userInfo 包含用户名、昵称、性别三个查询字段的用户信息
	 * @param page 当前页码数
	 * @param limit 一页显示条数
	 * @return 返回以状态码为0的，总记录数的，当前页码需要显示条数的用户列表。
	 */
	@ResponseBody
	@RequestMapping(value = "/selectUsersJoin",method = {RequestMethod.POST,RequestMethod.GET})
	public Result<UserInfo> selectUsersJoin(UserInfo userInfo) {
		List<UserInfo> list = indexService.selectUsersJoin(userInfo);
		return new Result<UserInfo>(0,"",indexService.countUsers(userInfo),list);
	}
	
	/**
	 * 获取当前用户所有菜单的接口，根据会话对象获取当前登陆人信息，并将其角色信息封装到菜单的实体类中，调用服务层以角色查询所有菜单的接口，并获取菜单列表。
	 * @return 返回以菜单实体类为泛型的结果集对象，并设置状态码为0，数据为菜单列表。
	 */
	@ResponseBody
	@RequestMapping(value = "/selectMenus",method = {RequestMethod.POST,RequestMethod.GET})
	public Result<MenuInfo> selectMenus(HttpSession session) {
		UserInfo userInfo = (UserInfo) session.getAttribute("USER_INFO");
		MenuInfo menuInfo = new MenuInfo();
		menuInfo.setRoleInfo(userInfo.getRoleInfo());
		return new Result<MenuInfo>(0,"",0L,indexService.selectMenus(menuInfo));
	}
	
	/**
	 * 查询所有角色的接口，直接调用服务层查询所有角色的接口，并返回结果。
	 * @return 返回有所的角色信息。
	 */
	@ResponseBody
	@RequestMapping(value = "/selectRoles",method = {RequestMethod.POST,RequestMethod.GET})
	public List<RoleInfo> selectRoles() {
		RoleInfo roleInfo = new RoleInfo();
		return indexService.selectRoles(roleInfo);
	}
	
	/**
	 * 修改单个用户信息的接口，即用户填写完基本资料后，点击提交按钮，由此接口通过判断主键判断是否为当前用户。
	 * @param userInfo 前台提交到后台的用户信息
	 * @return 如果不是当前用户则返回0，如果是当前用户，即调用服务层以主键修改用户指定字段的接口，并返回其结果。
	 */
	@ResponseBody
	@RequestMapping(value = "/updateSelectiveUser",method = {RequestMethod.POST,RequestMethod.GET})
	public Result<String> updateSelectiveUser(UserInfo userInfo) {
		if ((indexService.updateSelectiveUser(userInfo)) != 1) {
			return new Result<String>(1,"修改失败",0L,null);
		}
		return new Result<String>(0,"修改成功",0L,null);
	}
	
	/**
	 * 用户头像上传接口，另存为以用户名为文件名，以原图片扩展名为扩展名的图片，保存在静态资源目录下。
	 * 首先，通过图片的二进制流对象获取原文件名，与当前登陆人信息；
	 * 其次，生成文件保存路径与新文件名称；
	 * 最后，创建新文件对象，并通过图片的二进制流对象保存图片。
	 * @param file 用于接收头像图片的二进制流
	 * @return 失败返回状态为1，与原文件名；成功返回状态为0，与新文件名。
	 */
	@ResponseBody
	@RequestMapping(value = "/upload",method = {RequestMethod.POST,RequestMethod.GET})
    public Result<String> upload(@RequestParam MultipartFile file){
		String originalFileName = file.getOriginalFilename();
        String fileName = StrUtil.concat(true, UUID.randomUUID().toString(true),StrUtil.DOT,FileUtil.extName(originalFileName));
        File targetFile = new File(image_address, fileName);
        boolean targetFileExists = targetFile.exists();
        while (targetFileExists) {
        	fileName = StrUtil.concat(true, UUID.randomUUID().toString(true),StrUtil.DOT,FileUtil.extName(originalFileName));
        	targetFile = new File(image_address, fileName);
        	targetFileExists = targetFile.exists();
		}
        try {
        	file.transferTo(targetFile);
        } catch (Exception e) {
        	e.printStackTrace();
        	return new Result<String>(1,originalFileName,0L,null);
        }
        return new Result<String>(0,fileName,0L,null);
    }
	
	@ResponseBody
	@RequestMapping("/download")
	public String download(String fileName,HttpSession session, HttpServletRequest request, HttpServletResponse response){
		response.setContentType("text/html;charset=utf-8");
		try {
			request.setCharacterEncoding("UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		java.io.BufferedInputStream bis = null;
		java.io.BufferedOutputStream bos = null;
		try {
			long fileLength = new File(image_address,fileName).length();
			response.setContentType("application/x-msdownload;");
			response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("utf-8"), "ISO8859-1"));
			response.setHeader("Content-Length", String.valueOf(fileLength));
			bis = new BufferedInputStream(new FileInputStream(image_address+File.separator+fileName));
			bos = new BufferedOutputStream(response.getOutputStream());
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (bis != null)
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			if (bos != null)
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return null;	
	}
}
